#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time    : 2021/5/20 上午11:27
# @Author  : Samge
import re
from bs4 import BeautifulSoup
from scrapy import Selector

"""
清理html标签时，防止尖括号内的中文内容被清除的工具类

因为一般的html解析或者html标签处理时，
<>里面的内容都被识别为html标签
如果在清除html标签时对空标签进行清除，则<中文内容或其他内容>也会被清掉

    例如：
        v = '<td>省政府办公厅<江海区老旧污水1管网排查4></td>'
        
    1、使用BeautifulSoup处理html片段
        soup = BeautifulSoup(v, 'lxml')
        此时soup对象里面已经将 <江海区老旧污水1管网排查4> 这块内容过滤掉了
        
    1、使用Selector进行内容提取：
        v = ''.join(Selector(text=v).xpath('//*//text()').extract())
        此时已经将 <江海区老旧污水1管网排查4> 这块内容过滤掉了
        
    2、使用正则提取html中的正文：
        v = re.sub(r'<.*?>', '', v)
        此时已经将 <江海区老旧污水1管网排查4> 这块内容过滤掉了
"""


# 尖括号替换的占位标识
# 这里占位符没有用 '&lt;' 是因为在 Selector解析中，如果存在 &lt;内容&gt; 这样格式的内容，也会被认为是一个标签被清除掉
TAG_LEFT_ANGLE_BRACKETS = '$#TAG_LEFT_ANGLE_BRACKETS#$'


def protect_angle_brackets(value):
    """
    保护中文前面的尖括号
        如 <我是尖括号内的中文不要清除我> =》 {TAG_LEFT_ANGLE_BRACKETS}我是尖括号内的中文不要清除我>
    :param value:
    :return:
    """
    if not value:
        return value
    try:
        for r in re.findall(r'(?<=(\<))(?=((\d)|([\u4e00-\u9fa5])))', value, re.DOTALL) or []:
            r = r or []
            value = value.replace(f'{r[0]}{r[1]}', f'{TAG_LEFT_ANGLE_BRACKETS}{r[1]}')
    except:
        pass
    return value


def restore_angle_brackets(value, replace_v='<'):
    """
    恢复中文前面的尖括号
        如 {TAG_LEFT_ANGLE_BRACKETS}我是尖括号内的中文不要清除我> =》 <我是尖括号内的中文不要清除我>
    :param value:
    :param replace_v: 尖括号内容替换的字符，默认是 <
    :return:
    """
    return (value or '').replace(TAG_LEFT_ANGLE_BRACKETS, replace_v)


def __test_print_result(_v):
    """打印测试数据"""
    print(f'\t待处理数据：{_v}')

    temp_result = str(BeautifulSoup(_v, 'lxml').extract())
    print(f'\t使用BeautifulSoup加载的结果：{restore_angle_brackets(temp_result, replace_v="&lt;")}')

    temp_result = ''.join(Selector(text=_v).xpath('//*//text()').extract())
    print(f'\t使用Selector解析的结果：{restore_angle_brackets(temp_result)}')

    temp_result = re.sub(r'<.*?>', '', _v)
    print(f'\t使用正则解析的结果：{restore_angle_brackets(temp_result)}')


def __test_clean_script(text):
    """清除script"""
    if text and str(text).startswith('http'):
        return text
    soup = BeautifulSoup(text, 'lxml')
    for tag in soup.find_all(['script']):
        tag.decompose()
    return str(soup.extract())


if __name__ == '__main__':
    v = r'<td>省政府办公厅<江海区老旧污水1管网排查4><script>js脚本内容</script></td>'

    print('\n对尖括号内的中文内容进行保护前：')
    __test_print_result(v)

    print('\n对尖括号内的中文内容进行保护后：')
    __test_print_result(protect_angle_brackets(v))

    print('\n对尖括号内的中文内容进行保护 + 过滤script后：')
    __test_print_result(__test_clean_script(protect_angle_brackets(v)))

